package com.campus.counseling.service.impl;

import com.campus.counseling.service.EmotionDictionary;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class EmotionDictionaryImpl implements EmotionDictionary {

    // 风险关键词词典
    private Set<String> riskKeywords = new HashSet<>();
    
    // 情感词典 (词:分数)
    private Map<String, Double> emotionScores = new HashMap<>();
    
    // 情绪类型词典
    private Map<String, List<String>> emotionTypes = new HashMap<>();

    // 1. 定义转折词常量
    private static final List<String> TRANSITION_WORDS = Arrays.asList(
        "但是", "但", "虽然", "尽管", "即使", "可是", "不过"
    );

    @PostConstruct
    public void init() {
        try {
            // 加载风险关键词
            loadRiskKeywords();
            
            // 加载情感词典
            loadEmotionScores();
            
            // 加载情绪类型词典
            loadEmotionTypes();
            
            log.info("情感词典加载完成: 风险词{}个, 情感词{}个, 情绪类型{}个", 
                riskKeywords.size(), emotionScores.size(), emotionTypes.size());
        } catch (Exception e) {
            log.error("情感词典加载失败", e);
            throw new RuntimeException("情感词典加载失败", e);
        }
    }

    @Override
    // 从内容中提取风险关键词
    public List<String> extractRiskKeywords(String content) {
        // 判断内容是否为空
        if (!StringUtils.hasText(content)) {
            // 如果内容为空，返回空列表
            return Collections.emptyList();
        }
        
        // 创建一个列表，用于存储发现的风险关键词
        List<String> found = new ArrayList<>();
        // 遍历风险关键词列表
        for (String keyword : riskKeywords) {
            // 判断内容是否包含当前关键词
            if (content.contains(keyword)) {
                // 如果包含，将关键词添加到列表中
                found.add(keyword);
                // 记录日志，发现风险关键词
                log.info("发现风险关键词: {}", keyword);
            }
        }
        
        // 返回发现的风险关键词列表
        return found;
    }

    @Override
    // 根据内容判断情感类型
    public String determineEmotionType(String content) {
        // 如果内容为空，返回NEUTRAL
        if (!StringUtils.hasText(content)) {
            return "NEUTRAL";
        }
        
        // 计算每种情绪类型的匹配度
        Map<String, Integer> typeMatches = new HashMap<>();
        
        // 遍历每种情绪类型
        emotionTypes.forEach((type, words) -> {
            // 计算当前情绪类型中包含的词在内容中的数量
            int matches = (int) words.stream()
                .filter(content::contains)
                .count();
            // 如果有匹配的词，记录匹配的数量
            if (matches > 0) {
                log.info("情绪类型 {} 匹配到 {} 个词", type, matches);
            }
            // 将匹配的数量存入typeMatches中
            typeMatches.put(type, matches);
        });
        
        // 如果没有任何匹配，返回NEUTRAL
        if (typeMatches.values().stream().mapToInt(Integer::intValue).sum() == 0) {
            return "NEUTRAL";
        }
        
        // 返回匹配度最高的情绪类型
        return typeMatches.entrySet().stream()
            .max(Map.Entry.comparingByValue())
            .map(Map.Entry::getKey)
            .orElse("NEUTRAL");
    }

    @Override
    // 计算情感得分
    public double calculateEmotionScore(String content) {
        // 如果内容为空，则返回0.5
        if (content == null || content.isEmpty()) {
            return 0.5;
        }
        
        // 记录日志，开始计算情感得分，并记录内容长度
        log.info("开始计算情感得分，内容长度: {}", content.length());
        
        // 1. 分析风险词
        // 提取内容中的风险词
        List<String> riskWords = extractRiskKeywords(content);
        double riskScore = 0.0;
        
        // 如果有风险词，则计算风险分数
        if (!riskWords.isEmpty()) {
            riskScore = Math.min(1.0, 0.75 + (riskWords.size() * 0.15));
            // 记录日志，发现风险词和风险分数
            log.info("发现风险词: {}, 风险分数: {}", riskWords, riskScore);
        }
        
        // 2. 计算基础情感分数
        double positiveScore = 0.0;
        double negativeScore = 0.0;
        int positiveCount = 0;
        int negativeCount = 0;
        
        // 3. 检查转折词并记录位置
        boolean hasTransition = false;
        int transitionIndex = -1;
        
        // 遍历转折词列表
        for (String word : TRANSITION_WORDS) {
            // 在内容中查找转折词
            int index = content.indexOf(word);
            // 如果找到转折词，则记录位置
            if (index != -1) {
                hasTransition = true;
                transitionIndex = index;
                // 记录日志，发现转折词和位置
                log.info("发现转折词: {}, 位置: {}", word, index);
                break;
            }
        }
        
        // 遍历情绪类型列表
        for (Map.Entry<String, List<String>> entry : emotionTypes.entrySet()) {
            String type = entry.getKey();
            // 遍历情绪类型对应的单词列表
            for (String word : entry.getValue()) {
                // 如果内容中包含该单词
                if (content.contains(word)) {
                    // 根据情绪类型，增加相应的计数
                    if (type.equals("HAPPY") || type.equals("PEACEFUL") || type.equals("CONFIDENT")) {
                        positiveCount++;
                    } else if (type.equals("SAD") || type.equals("ANXIOUS") || type.equals("ANGRY") || 
                              type.equals("LONELY") || type.equals("DEPRESSED") || type.equals("STRESSED")) {
                        negativeCount++;
                    }
                }
            }
        }
        
        // 再检查情感分数词典
        for (Map.Entry<String, Double> entry : emotionScores.entrySet()) {
            // 获取情感得分表中的单词
            String word = entry.getKey();
            // 判断内容中是否包含该单词
            if (content.contains(word)) {
                // 获取情感得分
                double score = entry.getValue();
                // 如果情感得分大于0，则将情感得分累加到positiveScore，并将positiveCount加1
                if (score > 0) {
                    positiveScore += score;
                    positiveCount++;
                // 否则，将情感得分的绝对值累加到negativeScore，并将negativeCount加1
                } else {
                    negativeScore += Math.abs(score);
                    negativeCount++;
                }
            }
        }
        
        // 计算正面的平均分
        double avgPositive = positiveCount > 0 ? positiveScore / positiveCount : 0;
        // 计算负面的平均分
        double avgNegative = negativeCount > 0 ? negativeScore / negativeCount : 0;
        
        // 记录日志，情感分析详情
        log.info("情感分析详情: 积极(count={}, avg={}), 消极(count={}, avg={})", 
            positiveCount, avgPositive, negativeCount, avgNegative);
        
        // 7. 计算基础分数
        double baseScore;
        if (hasTransition && transitionIndex != -1) {
            // 根据转折后的情感倾向调整基础分数
            boolean isPositiveAfter = positiveCount > negativeCount;
            if (isPositiveAfter) {
                baseScore = 0.4 + (avgPositive * 0.3);  // 偏向积极
            } else {
                baseScore = 0.6 + (avgNegative * 0.3);  // 偏向消极
            }
        } else {
            baseScore = 0.5 + ((avgNegative - avgPositive) * 0.3);
        }
        
        // 8. 计算最终分数
        double finalScore;
        if (riskScore > 0) {
            if (hasTransition) {
                // 有风险词但也有转折词，降低风险分数的权重
                finalScore = (riskScore * 0.3) + (baseScore * 0.7);
            } else {
                // 纯风险文本，保持较高的风险权重
                finalScore = (riskScore * 0.8) + (baseScore * 0.2);
            }
        } else {
            finalScore = baseScore;
        }
        
        // 确保分数在0-1范围内
        finalScore = Math.max(0, Math.min(1, finalScore));
        
        log.info("情感分析结果: 基础分数={}, 风险分数={}, 最终分数={}", 
            baseScore, riskScore, finalScore);
        
        return finalScore;
    }

    // 加载风险关键词
    private void loadRiskKeywords() throws Exception {
        // 使用try-with-resources语句，自动关闭BufferedReader
        try (BufferedReader reader = new BufferedReader(
                // 使用InputStreamReader读取ClassPathResource中的文件，并指定字符集为UTF-8
                new InputStreamReader(
                    new ClassPathResource("dictionary/risk_keywords.txt")
                        .getInputStream(), StandardCharsets.UTF_8))) {
            
            String line;
            // 逐行读取文件内容
            while ((line = reader.readLine()) != null) {
                // 如果行内容不为空
                if (StringUtils.hasText(line)) {
                    // 将行内容去除首尾空格后添加到riskKeywords集合中
                    riskKeywords.add(line.trim());
                }
            }
        }
    }

    private void loadEmotionScores() throws Exception {
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(
                    new ClassPathResource("dictionary/emotion_scores.txt")
                        .getInputStream(), StandardCharsets.UTF_8))) {
            
            String line;
            while ((line = reader.readLine()) != null) {
                if (StringUtils.hasText(line)) {
                    String[] parts = line.split("\t");
                    if (parts.length == 2) {
                        emotionScores.put(parts[0].trim(), 
                            Double.parseDouble(parts[1].trim()));
                    }
                }
            }
        }
    }

    private void loadEmotionTypes() throws Exception {
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(
                    new ClassPathResource("dictionary/emotion_types.txt")
                        .getInputStream(), StandardCharsets.UTF_8))) {
            
            String line;
            while ((line = reader.readLine()) != null) {
                if (StringUtils.hasText(line)) {
                    String[] parts = line.split("\t");
                    if (parts.length == 2) {
                        String type = parts[0].trim();
                        List<String> words = Arrays.asList(parts[1].split(","));
                        emotionTypes.put(type, words);
                    }
                }
            }
        }
    }
} 